/**
 * @(#)SerializadorProperties 16/07/13
 *
 * Copyright (c) 2005-2015 PsiqueWare S.A. de C.V. All Rights Reserved.
 * This software is the proprietary information PsiqueWare S.A. de C.V.
 * Use is subject to license terms.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * <br/>Usuario : AngelElectrico
 * <br/>Creaci&oacute;n:16/07/13 - 08:09 PM PM
 * <br/>
 * <br/>
 * <br/><t5>Cambios :</t5>
 * <br/><b>Fecha | Autor  |  Cambios</b>
 * <ul>
 * <li>16/07/13 | <a href = "mailto:AngelElectrico@PsiqueWare.com">&Aacute;ngel El&eacute;ctrico</a> | Creaci&oacute;n del Objeto.</li>
 *
 * </ul>
 */
package com.psiqueware.alheli.serializacion.serializadores;

import com.psiqueware.alheli.exception.NullArgumentException;
import com.psiqueware.alheli.exception.NullConditionException;
import com.psiqueware.alheli.reflection.RefleccionClases;
import com.psiqueware.alheli.reflection.RefleccionMetodos;
import com.psiqueware.alheli.serializacion.Serializador;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.util.Date;
import java.util.List;

/**
 * Serializa la informaci&oacute;n contenida en un pojo con un constructor sin argumentos.
 * <p/>
 * <br/>Paquete Original: com.psiqueware.alheli.serializacion.serializadores
 * <br/>Nombre  Original: SerializadorProperties
 * <br/>Oprima para ver : <a href="SerializadorProperties.java.html"><i>C&oacute;digo Fuente</i> </a>
 *
 * @author <a href="mailto:AngelElectrico@PsiqueWare.com">&Aacute;ngel El&eacute;ctrico</a>
 * @version Revision: 1.1 16/07/13 08:09 PM
 */
public final class SerializadorProperties implements Serializador
{

    /**
     * Clase del objeto para el que va a funcionar el {@link Serializador}.
     */
    private final Class m_claseBasePojo;

    /**
     * Nombres de los atributos que se pueden serializar de la clase base.
     */
    private final List<String> m_nombresAtributosBasicos;

    /**
     * Constructor de SerializadorProperties.
     */
    public SerializadorProperties(final Class claseBasePojo)
    {
        if (null == claseBasePojo)
            throw new NullArgumentException("<error>El argumento 'claseBasePojo' no puede ser NULL.</error>");
        m_claseBasePojo = claseBasePojo;
        m_nombresAtributosBasicos = RefleccionMetodos.listaNombresAtributosBasicos(m_claseBasePojo);
    }


    /**
     * Convierte un {@link java.io.Serializable} a su representaci&oacute;n en una cadena.
     *
     * @param serializable a convertir.
     *
     * @return cadena con el objeto serializado.
     */
    @Override
    public String serializar(final Serializable serializable)
    {
        if (null == serializable)
            throw new NullArgumentException("<error>El argumento 'serializable' no puede ser NULL.</error>");
        if (!m_claseBasePojo.isInstance(serializable))
            throw new NullConditionException("<error>El serializable deb&iacute;a ser de la clase '" + m_claseBasePojo + "' y es de la clase '" + serializable.getClass() + "'.</error>");

        final StringBuilder sb = new StringBuilder("#" + m_claseBasePojo + "\n#" + new Date());
        for (final String nombreAtributoBasico : m_nombresAtributosBasicos)
        {
            final String getter = RefleccionMetodos.buscaNombreMetodoGetter(m_claseBasePojo, nombreAtributoBasico);
            if (null != getter)
            {
                final String valor = RefleccionMetodos.ejecutaFuncionGetterBasicoCasting(serializable, getter);
                sb.append('\n').append(nombreAtributoBasico).append("=").append(valor);
            }
        }
        return sb.toString();
    }

    /**
     * Convierte una cadena que representa un {@link java.io.Serializable} a su objeto representadol.
     *
     * @param cadena a convertir.
     *
     * @return el {@link java.io.Serializable} convertido.
     */
    @Override
    public Serializable objetivizar(final String cadena)
    {
        if (null == cadena) throw new NullArgumentException("<error>El argumento 'cadena' no puede ser NULL.</error>");
        final Serializable pojo = (Serializable) RefleccionClases.nuevaInstancia(m_claseBasePojo);
        final String[] instrucciones = cadena.split("\n");
        for (final String instruccion : instrucciones)
        {
            if (!instruccion.startsWith("#") && instruccion.contains("="))
            {
                final int partir = instruccion.indexOf('=');
                final String nombreAtributo = instruccion.substring(0, partir);
                final String valor = instruccion.substring(partir + 1, instruccion.length());
                final String setter = RefleccionMetodos.buscaNombreMetodoSetter(m_claseBasePojo, nombreAtributo);
                if (null != setter)
                {
                    try
                    {
                        RefleccionMetodos.ejecutaMetodoSetterBasicoCasting(pojo, valor, setter);
                    }
                    catch (NoSuchMethodException e)
                    {
                        throw new RuntimeException(e);
                    }
                    catch (IllegalAccessException e)
                    {
                        throw new RuntimeException(e);
                    }
                    catch (InvocationTargetException e)
                    {
                        throw new RuntimeException(e);
                    }
                    catch (ParseException e)
                    {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        return (Serializable) pojo;
    }
}

